﻿/****************************************************************
  Author:  Ievgenii Nazaruk, ievgenii.nazaruk@gmail.com 
 License:  Microsoft Public License (Ms-PL)
          ( http://www.opensource.org/licenses/ms-pl.html or
            http://www.microsoft.com/opensource/licenses.mspx )
*****************************************************************/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using TableParsers;
using WebLayer;
using WebPageParser;
using System.Collections.Specialized;
using System.Collections.Observable;

namespace SpeakupBackend.Classes
{
    [Serializable]
    public class ClassList: ObservableList<Class>
    {

        #region Refresh functionality 

        [Flags]
        public enum RefreshType { FutureClasses = 1, PastClasses = 2, AllClasses = 3 }

        public void Refresh(RefreshType refreshType, WebPageCache webCache)
        {
            ClassList oldClasses = new ClassList();
            oldClasses.AddRange(this);
            
            //remove old classes 
            Clear();

            //fetch new classes
            ClassList newClasses = new ClassList();

            if ( (refreshType & RefreshType.FutureClasses) == RefreshType.FutureClasses)
            {
                newClasses.AddRange(ClassListFetcher.FetchFutureClasses(webCache));
            }

            if ( (refreshType & RefreshType.PastClasses) == RefreshType.PastClasses)
            {
                newClasses.AddRange(ClassListFetcher.FetchPastClasses(webCache));
            }

            ClassListFetcher.RemoveClassDuplicates(newClasses);
            

            //get modified
            List<Class> modified = (from n in oldClasses
                                    where n.Action != ClassAction.None
                                    select n).ToList();
            
            //restore modified statuses
            foreach (Class speakupClass in newClasses)
            {
                Class match = modified.FirstOrDefault(a => 
                                                      {
                                                        return speakupClass.Equals(a); 
                                                      });

                if (match != null && match.Action != ClassAction.None)
                {
                    if (speakupClass.CurrentStatus == match.CurrentStatus)
                    {
                        speakupClass.Action = match.Action;
                    }                
                }
            }
            
            AddRange(newClasses);           
        }

        public void Refresh(RefreshType refreshType, LoginToken loginToken)
        {
            WebPageCache webCache = new WebPageCache();
            webCache.LoginToken = loginToken;

            Refresh(refreshType, webCache);
        }

        #endregion

        #region Persistency

        /// <summary>
        /// Load list from specified file.
        /// </summary>
        /// <param name="fileName">File name</param>
        /// <returns>Loaded class list</returns>
        static public ClassList Load(String fileName)
        {
            IFormatter formatter = new BinaryFormatter();
            ClassList list = null;
            using (FileStream s = File.OpenRead(fileName))
            {
                list = (ClassList)formatter.Deserialize(s);
            }
            return list;
        }

        /// <summary>
        /// Load list from specified file and merges it into current list.
        /// </summary>
        /// <param name="fileName">File name</param>
        /// <returns>Loaded class list</returns>
        public void Reload(String fileName)
        {
            Clear();
            ClassList newList = ClassList.Load(fileName);
            AddRange(newList);
        }

        /// <summary>
        /// Saves list to specified file
        /// </summary>
        /// <param name="fileName"></param>
        public void Save(String fileName)
        {
            IFormatter formatter = new BinaryFormatter();
            using (FileStream s = File.Create(fileName))
            {
                formatter.Serialize(s, this);
            }
        }

        #endregion
    }
}
